﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.Threading;

namespace Glissando
{
    // http://team.interknowlogy.com/blogs/paulrohde/archive/2009/08/05/building-a-really-simple-wcf-p2p-application.aspx

    [ServiceContract(CallbackContract = typeof(IJamService))]
    public interface IJamService
    {
        [OperationContract(IsOneWay = true)]
        void Say(string sender, string message);

        [OperationContract(IsOneWay = true)]
        void Play(Guid sender, int cmd, int ch, int data1, int data2);

        [OperationContract(IsOneWay = true)]
        void Hello(Guid sender, string alias, string location);

        [OperationContract(IsOneWay = true)]
        void Goodbye(Guid sender);
    }

    public class JamPeer
    {
        public Guid Id { get; private set; }
        public string Room { get; private set; }

        public IJamService Channel;
        public IJamService Host;
        public event Action Connected;

        public JamPeer(Guid id, string room, IJamService host)
        {
            Id = id;
            Host = host;
            Room = room;
        }

        public void StartService()
        {
            var binding = new NetPeerTcpBinding();
            binding.Security.Mode = SecurityMode.None;

            var endpoint = new ServiceEndpoint(
                ContractDescription.GetContract(typeof(IJamService)),
                binding,
                new EndpointAddress("net.p2p://glissando/" + Room));

            _factory = new DuplexChannelFactory<IJamService>(new InstanceContext(Host), endpoint);

            var channel = _factory.CreateChannel();

            ((ICommunicationObject)channel).Open();

            // wait until after the channel is open to allow access.
            Channel = channel;
        }
        public void StopService()
        {
            ((ICommunicationObject)Channel).Close();
            if (_factory != null)
                _factory.Close();
        }
        public bool IsConnected
        {
            get { return _connected; }
        }
        private DuplexChannelFactory<IJamService> _factory;
        private readonly AutoResetEvent _stopFlag = new AutoResetEvent(false);
        private bool _connected = false;
        public void Run()
        {
            _connected = false;
            Debug.WriteLine("[ Starting Service ]");
            StartService();

            _connected = true;
            if (Connected != null)
                Connected.Invoke();

            Debug.WriteLine("[ Service Started ]");
            _stopFlag.WaitOne();

            Debug.WriteLine("[ Stopping Service ]");
            StopService();

            Debug.WriteLine("[ Service Stopped ]");
        }

        public void Stop()
        {
            _stopFlag.Set();
        }
    }

}


